/**
   * GULP自动化构建
   * 预期目标:
   * 1.打包css,js,html,image,font,
   * 2.处理public文件
   * 3.生成clean方法
   * 4.生成server
   * 5.完成开发和生产构建逻辑
   * 6.实现监听功能
   * 实现过程:
   * 1.打包CSS:
   *  1. 引入gulp-sass转换sass文件
   * 2.打包js:
   *  1.引入gulp-babel处理Js文件
   *  2.安装@babel/core,@babel/preset-env 引入babel核心模块
   *  3.通过babel({presets:['@babel/preset-env']}) 处理js新特性
   * 3.打包html:
   *  通过gulp-swig处理html模板
   * 4.打包image,font:
   *  通过imagemin 处理image文件,同时可以处理font中的svg格式
   * 5.clean
   *  通过del,实现删除文件
   * 6.依赖加载: 
   *  通过load-plugins实现自动加载插件,后续插件使用可通过plugins.的形式加载
   * 7.server:
   *  通过browser-sync 实现开发服务器
   */
const { src, dest, parallel,series,watch} = require('gulp')
const loadPlugins = require('gulp-load-plugins')()
const plugins = loadPlugins
const del = require('del')
// browser-sync 开发服务器
const browserSync = require('browser-sync')
const bs = browserSync.create()

const URL = 'src/assets/'

/** 删除 */
const clean = ()=>{
    // 删除dist及目录下的文件
    return del(['dist'])
}

/** 样式处理 */
const styles = ()=>{
    return src(`${URL}styles/*.scss`,{base:'src'})// base参数可以指定文件读取路径
    .pipe(plugins.sass({outputStyle:'expanded'})) // outputStyle 指定转换后的格式
    .pipe(dest('dist'))
}

// html文件编译
const page = ()=>{
    return src(`${URL}script/*.html`,{base:'src'}) 
    .pipe( plugins.swig({data:''}))  // data转换模板中的变量
    .pipe(dest('dist'))
}

/** 脚本文件 */
const scripts = ()=>{
    return src(`${URL}script/*.js`,{base:'src'})
    .pipe(plugins.babel({presets:['@babel/preset-env']}))
    .pipe(dest('dist'))
}

/** 处理图片 */
const images = () =>{
    return src(`${URL}images/*.{jpg,gif,ico}`,{base:'src/assets'})
    .pipe(plugins.imagemin())
    .pipe(dest('dist'))

}

/** 处理文字 */
const fonts = () =>{
    return src(`${URL}fonts/**`,{base:'src'})
    .pipe(dest('dist'))
}

const extra = ()=>{
    return src('public/**',{base:'public'})
    .pipe(plugins.imagemin())
    .pipe(dest('dist'))
}

// 处理文件引用
const useref = ()=>{
    // 这里会产生BUG,读写不成功,原因是读写流的文件一致,都是dist目录,
    return src('dist/*.html',{base:'src'})
    .pipe(plugins.useref({searchPath:['dist','.']})) // 合并文件
    // html js css 文件压缩 gulp-if 插件,执行判断逻辑
    .pipe(plugins.if(/\.js$/,plugins.uglify()))
    .pipe(plugins.if(/\.css$/,plugins.cleanCss()))
    .pipe(plugins.if(/\.html$/,plugins.htmlmin({collapseWhitespace:true,minifyCSS:true,minifyJS:true}))) // collapseWhitespace 压缩空格符 ;minifyCSS,minifyJS压缩行内样式和脚本
    //.pipe(dest('dist'))
    .pipe(dest('release')) // 解决读写一致的BUG,写入额外的目录
}

const serve = ()=>{
     // 监视文件,更新后执行回调
    watch(`${URL}styles/*.scss`,styles) // xxx.scss 文件更新后,执行style
    watch(`${URL}script/*.js`,scripts) 
    watch(`${URL}script/*.html`,page) 
    // 开发阶段不必要监听和执行压缩,只需在发布构建中处理即可
    // watch('images/**',image) 
    // watch('font/**',font) 
    // watch('public/**',extra) 
    // 通过该方法,可以实现当静态文件发生变化时执行热更新,同时减少构建次数
    watch([
        `${URL}images/**`,
        `${URL}fonts/**`,
        'public/**',
    ],bs.reload)

     bs.init({
        server:{
            notify:false, // 关闭连接提示,
            port:8000,
            open:false, // 自动打开浏览器
            baseDir:['dist','src','public'], // 开发阶段不监听静态文件时,会依目录顺序去查找静态文件
            files:'dist/**', // 监听文件地址,执行热更新 或者通过pipe(bs.reload()的方式推送更新)
            routes:{
                // 优先于baseDir 会先找routes,找不到再找baseDir
                '/node_modules':'node_modules'
            }
        }
    })
}


const compile = parallel(styles,scripts,page,images,fonts)
/**
* 通过同步,先执行clean任务,再执行build
* 上线前的打包
*/
const build = series(clean,parallel(series(compile,useref),images,fonts,extra))

const develop = series(compile,serve)

module.exports = {
    clean,
    build,
    develop,
}